Javascript 함수 선언 방법과 호이스팅
함수 선언 방법
함수선언문 (Function Declaration)
// 일반적인 함수 선언 방법
function add(a, b) {
return a + b
}
함수표현식 (Function expression)
// arrow function으로 함수표현식 선언 방법
const myFunc1 = () => { } // 매개변수가 없을 경우
const myFunc2 = x => { } // 매개변수가 한 개인 경우, 소괄호를 생략 가능
const myFunc3 = (x, y) => { } // 매개변수가 여러 개인 경우, 소괄호를 생략 불가
// Body 전개 방법
const myFunc4 = x => { return x * 2 } // single line block
const myFunc5 = x => x * 2 // 함수 몸체가 한줄의 구문이라면 중괄호 생략 가능
const myFunc6 = () => { return { a: 1 }}
const myFunc7 = () => ({ a: 1 }) // 위 표현과 동일. 객체 반환시는 소괄호를 사용.
호이스팅(hoisting)
예제 부터 보면
hoistFunc();
function hoistFunc(){ console.log('함수 선언이 아래에 있지만 문제 없어요') }
자바스크립트는 실행되기 전에 필요한 함수와 변수들을 모두 모아서 유효 범위의 최상단에 선언한다. 이를 호이스팅이라고 한다. hoisting
[명사] 끌어 올리기, 들어올려 나르기.
호이스팅 되는 놈 : 함수선언문
, var
(단, 선언만 끌어 올려지고 값은 끌어올려지지 않음)
호이스팅 안되는 놈 : 함수표현식
, let
, const
왜 안해줌?
파서가 안해줌.
개발 실수도 줄여주고 나쁘지 않은 방향. 되는 놈은 하위 호환 유지를 위해 여전히 지원하는것 뿐.
func1(message); // 함수 func1과 message가 선언되기 전에 함수를 호출 하였지만 호이스팅됨.
function func1(message){
console.log('your message is ' + message); // your message is undefined
}
var message = '안녕'; // 안녕 이라는 값은 호이스팅되지 않아 undefined로 출력된다.
func1 선언과 message 변수 선언이 호이스팅 되어 에러 없이 동작한다. 단, 값이 호이스팅 되지 않아 undefined 로 처리 된다.
// 변수를 선언하지 않는 경우
func2(msg); // Uncaught ReferenceError 발생
function func2(msg){
console.log(msg);
}
func2의 경우 호이스팅 되어 문제 없으나 msg 변수는 선언이 되지 않아 에러 발생한다.
console.log(name); // undefined
var name = 'hwan77';
// 위의 코드는 실제로 실행될 때 아래와 같이 처리됨.
var name;
console.log(name); // undefined
name = 'hwan77';
function과 arrow function 의 차이점(3가지가 없는 놈)
1) 이름이 없다.
Arrow function은 익명 함수라는 점.
//일반 function
function myFunc(){
console.log("hwan77")
}
//arrow function
() => {
console.log("Nameless ㅠㅠ")
}
//참조해서 다른곳에서 쓰려면? const myFunc = () => {}
2) this가 없다.
Arrow function은 자신의 this가 없다.
arrow function은 외부에 있던 this를 그대로 내부로 가져와서 사용한다.
자바스크립트에서 this는 그 용법이 특이하다. 요약하자면 es5에서의 this는 이렇다.
- 함수 실행시에는 전역(window) 객체를 가리킨다.
- 메소드 실행시에는 메소드를 소유하고 있는 객체를 가리킨다.
- 생성자 실행시에는 새롭게 만들어진 객체를 가리킨다.
// this example
let myInfo={
name: "hwan77",
print: function(){
console.log(this, this.name);
}
};
myInfo.print(); // {name: 'hwan77', print: ƒ} 'hwan77'
let myInfo={
name: "hwan77",
print: () => {
console.log(this, this.name);
}
};
myInfo.print(); // window ''
const o = {
name: 'Kim',
speak: function () {
function getName() { return `${this.name}`; } // 여기서의 this는 window 객체이다. 함수 실행시에는 전역(window) 객체를 가리킨다
return `My name is ${getName()}`;
}
};
o.speak(); // "My name is "
const o = {
name: 'Kim',
speak: function() {
const getName = () => { return `${this.name}`; } // 여기에서의 this는 o라는 객체
return `My name is ${getName()}`;
}
};
o.speak(); // "My name is Kim"
// arrow function은 맥락 상 위의 코드부터 보고 결합
3) arguments가 없다.
Arrow function은 arguments가 없다.
// 일반 function
function func1() {
console.log(arguments[0]); // 1
console.log(arguments[1]); // 2
console.log(arguments[2]); // undefined
}
func1(1, 2);
// Arrow function
const myFunc2 = () => {
console.log(arguments); // error
}
myFunc2(1, 2);
위 코드를 실행시켜보면
그래서 Arrow function의 경우 arguments를 추가 시켜주기 위해서는 전개 연산자를 활용해 arguments를 직접 명시해주어야 한다!
// 전개연산자 사용
const myFunc2 = (...arguments) => {
console.log(arguments); // [1, 2, 3, 4]
}
myFunc2(1, 2, 3, 4);